package MySQL::Describe;

use 5.008;
use strict;

our $VERSION = '0.01';

use Carp;
use Text::Table;

use base qw(Class::Accessor::Fast Exporter);
__PACKAGE__->mk_accessors(qw(dbh results cur_num count));

our @EXPORT_OK = qw(describe_table);

sub describe_table {
      my $table = shift;
      my %args = @_;
      return __PACKAGE__->new( %args )->describe( $table );
}

sub new {
      my $proto = shift;
      my %args = @_;
      my $class = ref($proto) || $proto;
      my $self = $class->SUPER::new( \%args );
            $self->init;
      return $self;
}

sub init {
      my $self = shift;
     
      die "Database handle (dbh) is mandatory"
            unless $self->dbh;
      $self->cur_num(0);
}

sub desc { shift->describe(@_) }  #shortcut

sub describe {
      my $self = shift;
      my $table = shift || croak "Table is mandatory argument";
      my %args = @_;

      my $sql = "DESCRIBE $table";

      my $sth = $self->dbh->prepare($sql);
      $sth->execute();
    
      my @result = ();
      while ( my $val = $sth->fetchrow_hashref ) {
            push @result , $val;
      }
      
      $self->count( scalar @result );
      $self->results( \@result );
    
      return $self;
}

sub next {
      my $self = shift;
	
      croak "describe() should be called before next_table()" unless $self->results;
      if ($self->cur_num >= $self->count) {
	    $self->cur_num(0); # auto flush 
	    return; 
      }
      	
      my $row = $self->results->[$self->cur_num];
      $self->cur_num($self->cur_num + 1);
	
      return $row;
}

sub print {
      my $self = shift;
    
      my $res = $self->results or return;
      my $table = Text::Table->new(keys %{$res->[0]});

      for (@$res) {
            $table->add(values %{$_});
      }
    
      print $table;
}



=head1 NAME

MySQL::Describe

=head1 SYNOPSIS

    use MySQL::Describe qw(describe_table);

    my $dbh = DBI->connect("dbi:mysql:db" , "test" , "test" , {RaiseError => 1, AutoCommit => 1});

    # functional constructor
    my $describe = describe_table("table1", dbh => $dbh);

    # OO way
    my $describe = MySQL::Describe->new( dbh => $dbh )->describe( "table1" );

    my $results = $describe->results;
   
    
    $describe->print;

=head1 DESCRIPTION

=head1 FUNCTIONS

=head2 describe_table

Takes a table. Constructs a new object of class
L<MySQL::Describe> and describes it at once.

Options are combination of L</new> and L</describe> methods' arguments,
for example:

      describe_table(
        "table1",
        dbh => $dbh,
        
      );

=head1 METHODS

=head2 new

=head2 describe

=head2 desc
      
      Short alias for describe

=head2 print

=head1 AUTHOR

Mikhail Maluyk E<lt>mikhail.maluyk@gmail.comE<gt>

=head1 LICENSE

This package is distributed under the same terms as perl itself.

=cut

1;
